package core.handler;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * HashMap 结果集
 *
 * @author Feny
 * @date Created in 2022/4/26
 */
public class BeanRowMapper<T> implements RowMapper<T> {
    /**
     * 实体类
     */
    private Class<T> mappedClass;
    /**
     * 实体属性字段
     */
    private Map<String, Field> mappedFields;

    public BeanRowMapper(Class<T> mappedClass) {
        initialize(mappedClass);
    }

    /**
     * 初始化字段信息
     *
     * @param mappedClass 实体类
     * @author Feny
     * @date 2022/7/12
     */
    private void initialize(Class<T> mappedClass) {
        this.mappedClass = mappedClass;
        this.mappedFields = new HashMap<>();
        Field[] fields = mappedClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(Boolean.TRUE);
            String fieldName = field.getName();
            String hump = humpToLine(fieldName);
            String toHump = lineToHump(fieldName);
            mappedFields.putIfAbsent(hump, field);
            mappedFields.putIfAbsent(toHump, field);
            mappedFields.putIfAbsent(fieldName, field);
            mappedFields.putIfAbsent(hump.toUpperCase(), field);
            mappedFields.putIfAbsent(toHump.toUpperCase(), field);
            mappedFields.putIfAbsent(fieldName.toUpperCase(), field);
        }
    }

    @Override
    public T mapRow(ResultSet rs) throws SQLException {
        ResultSetMetaData rsmd = rs.getMetaData();
        int columnCount = rsmd.getColumnCount();
        try {
            T instance = mappedClass.newInstance();
            for (int i = 1; i <= columnCount; i++) {
                Field field = mappedFields.get(getColumn(rsmd, i));
                if (Objects.nonNull(field)) {
                    field.set(instance, rs.getObject(i));
                }
            }
            return instance;
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }


    private static final Pattern HUMP_PATTERN = Pattern.compile("[A-Z]");
    private static final Pattern LINE_PATTERN = Pattern.compile("_(\\w)");

    /**
     * 驼峰转下划线
     */
    private String humpToLine(String str) {
        Matcher matcher = HUMP_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0));
        }
        matcher.appendTail(sb);
        return sb.toString().toLowerCase();
    }

    /**
     * 下划线转驼峰
     */
    public static String lineToHump(String str) {
        Matcher matcher = LINE_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }
}
